home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 365_02 / regsub.c < prev    next >
C/C++ Source or Header  |  1992-04-04  |  5KB  |  244 lines

  1. /* regsub.c */
  2.  
  3. /* This file contains the regsub() function, which performs substitutions
  4.  * after a regexp match has been found.
  5.  */
  6.  
  7. #include "config.h"
  8. #include "ctype.h"
  9. #include "vi.h"
  10. #include "regexp.h"
  11.  
  12.  
  13. /* perform substitutions after a regexp match */
  14. void regsub(re, src, dst)
  15.     regexp        *re;    /* the regexp with pointers into matched text */
  16.     REG char    *src;    /* the replacement string */
  17.     REG char    *dst;    /* where to put the result of the subst */
  18. {
  19.     REG char    *cpy;    /* pointer to start of text to copy */
  20.     REG char    *end;    /* pointer to end of text to copy */
  21.     REG char    c;
  22.     char        *start;
  23. #ifndef CRUNCH
  24.     int        mod = 0;/* used to track \U, \L, \u, \l, and \E */
  25.     int        len;    /* used to calculate length of subst string */
  26.     static char    *prev;    /* a copy of the text from the previous subst */
  27.  
  28.     /* replace \~ (or maybe ~) by previous substitution text */
  29.  
  30.     /* step 1: calculate the length of the new substitution text */
  31.     for (len = strlen(src), c = '\0', cpy = src; *cpy; cpy++)
  32.     {
  33. # ifdef NO_MAGIC
  34.         if (c == '\\' && *cpy == '~')
  35. # else
  36.         if (c == (*o_magic ? '\0' : '\\') && *cpy == '~')
  37. # endif
  38.         {
  39.             if (!prev)
  40.             {
  41.                 regerror("No prev text to substitute for ~");
  42.                 return;
  43.             }
  44.             len += strlen(prev) - 1;
  45. # ifndef NO_MAGIC
  46.             if (!*o_magic)
  47. # endif
  48.                 len -= 1; /* because we lose the \ too */
  49.         }
  50.  
  51.         /* watch backslash quoting */
  52.         if (c != '\\' && *cpy == '\\')
  53.             c = '\\';
  54.         else
  55.             c = '\0';
  56.     }
  57.  
  58.     /* allocate memory for the ~ed version of src */
  59.     start = cpy = (char *)malloc((unsigned)(len + 1));
  60.     if (!cpy)
  61.     {
  62.         regerror("Not enough memory for ~ expansion");
  63.         return;
  64.     }
  65.  
  66.     /* copy src into start, replacing the ~s by the previous text */
  67.     while (*src)
  68.     {
  69. # ifndef NO_MAGIC
  70.         if (*o_magic && *src == '~')
  71.         {
  72.             strcpy(cpy, prev);
  73.             cpy += strlen(prev);
  74.             src++;
  75.         }
  76.         else if (!*o_magic && *src == '\\' && *(src + 1) == '~')
  77. # else /* NO_MAGIC */
  78.         if (*src == '\\' && *(src + 1) == '~')
  79. # endif /* NO_MAGIC */
  80.         {
  81.             strcpy(cpy, prev);
  82.             cpy += strlen(prev);
  83.             src += 2;
  84.         }
  85.         else
  86.         {
  87.             *cpy++ = *src++;
  88.         }
  89.     }
  90.     *cpy = '\0';
  91. #ifdef DEBUG
  92.     if ((int)(cpy - start) != len)
  93.     {
  94.         msg("Bug in regsub.c! Predicted length = %d, Actual length = %d", len, (int)(cpy - start));
  95.     }
  96. #endif
  97.  
  98.     /* remember this as the "previous" for next time */
  99.     if (prev)
  100.         free(prev);
  101.     prev = src = start;
  102.  
  103. #endif /* undef CRUNCH */
  104.  
  105.     start = src;
  106.     while ((c = *src++) != '\0')
  107.     {
  108. #ifndef NO_MAGIC
  109.         /* recognize any meta characters */
  110.         if (c == '&' && *o_magic)
  111.         {
  112.             cpy = re->startp[0];
  113.             end = re->endp[0];
  114.         }
  115.         else
  116. #endif /* not NO_MAGIC */
  117.         if (c == '\\')
  118.         {
  119.             c = *src++;
  120.             switch (c)
  121.             {
  122. #ifndef NO_MAGIC
  123.               case '0':
  124.               case '1':
  125.               case '2':
  126.               case '3':
  127.               case '4':
  128.               case '5':
  129.               case '6':
  130.               case '7':
  131.               case '8':
  132.               case '9':
  133.                 /* \0 thru \9 mean "copy subexpression" */
  134.                 c -= '0';
  135.                 cpy = re->startp[c];
  136.                 end = re->endp[c];
  137.                 break;
  138. # ifndef CRUNCH
  139.               case 'U':
  140.               case 'u':
  141.               case 'L':
  142.               case 'l':
  143.                 /* \U and \L mean "convert to upper/lowercase" */
  144.                 mod = c;
  145.                 continue;
  146.  
  147.               case 'E':
  148.               case 'e':
  149.                 /* \E ends the \U or \L */
  150.                 mod = 0;
  151.                 continue;
  152. # endif /* not CRUNCH */
  153.               case '&':
  154.                 /* "\&" means "original text" */
  155.                 if (*o_magic)
  156.                 {
  157.                     *dst++ = c;
  158.                     continue;
  159.                 }
  160.                 cpy = re->startp[0];
  161.                 end = re->endp[0];
  162.                 break;
  163.  
  164. #else /* NO_MAGIC */
  165.               case '&':
  166.                 /* "\&" means "original text" */
  167.                 cpy = re->startp[0];
  168.                 end = re->endp[0];
  169.                 break;
  170. #endif /* NO_MAGIC */
  171.               default:
  172.                 /* ordinary char preceded by backslash */
  173.                 *dst++ = c;
  174.                 continue;
  175.             }
  176.         }
  177. #ifndef CRUNCH
  178. # if OSK
  179.         else if (c == '\l')
  180. # else
  181.         else if (c == '\r')
  182. # endif
  183.         {
  184.             /* transliterate ^M into newline */
  185.             *dst++ = '\n';
  186.             continue;
  187.         }
  188. #endif /* !CRUNCH */
  189.         else
  190.         {
  191.             /* ordinary character, so just copy it */
  192.             *dst++ = c;
  193.             continue;
  194.         }
  195.  
  196.         /* Note: to reach this point in the code, we must have evaded
  197.          * all "continue" statements.  To do that, we must have hit
  198.          * a metacharacter that involves copying.
  199.          */
  200.  
  201.         /* if there is nothing to copy, loop */
  202.         if (!cpy)
  203.             continue;
  204.  
  205.         /* copy over a portion of the original */
  206.         while (cpy < end)
  207.         {
  208. #ifndef NO_MAGIC
  209. # ifndef CRUNCH
  210.             switch (mod)
  211.             {
  212.               case 'U':
  213.               case 'u':
  214.                 /* convert to uppercase */
  215.                 *dst++ = toupper(*cpy++);
  216.                 break;
  217.  
  218.               case 'L':
  219.               case 'l':
  220.                 /* convert to lowercase */
  221.                 *dst++ = tolower(*cpy++);
  222.                 break;
  223.  
  224.               default:
  225.                 /* copy without any conversion */
  226.                 *dst++ = *cpy++;
  227.             }
  228.  
  229.             /* \u and \l end automatically after the first char */
  230.             if (mod && (mod == 'u' || mod == 'l'))
  231.             {
  232.                 mod = 0;
  233.             }
  234. # else /* CRUNCH */
  235.             *dst++ = *cpy++;
  236. # endif /* CRUNCH */
  237. #else /* NO_MAGIC */
  238.             *dst++ = *cpy++;
  239. #endif /* NO_MAGIC */
  240.         }
  241.     }
  242.     *dst = '\0';
  243. }
  244.